package cn.shujuhai.common.aop;

import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;

/**
 * @Author: ZhangDeZhong
 * @Date: 2024/12/12 09:24
 * @Description: 保证接口幂等性的切面处理类
 **/
@Aspect
@Component
@RequiredArgsConstructor
public class IdempotentAspect {

    private final CacheManager cacheManager;
    private final HttpServletRequest request;
    private static final Logger logger = LoggerFactory.getLogger(SysLogAspect.class);

    @Pointcut("@annotation(Idempotent)") // 拦截有 @Idempotent 注解的方法
    public void idempotentMethods() {
    }

    @Before("idempotentMethods()")  // 在方法执行前检查幂等性
    public void checkIdempotent() throws Throwable {
        // 获取请求中的 Request-ID
        String requestId = request.getHeader("Request-ID");

        if (requestId == null || requestId.isEmpty()) {
            logger.info("Missing Request");
            throw new RuntimeException("Missing Request");
        }

        // 获取名为 "idempotentCache" 的缓存实例
        Cache cache = cacheManager.getCache("idempotentCache");

        if (cache == null) {
            logger.info("Internal Server Error: Cache not found");
            throw new RuntimeException("Internal Server Error: Cache not found");
        }

        // 检查缓存中是否已经有该请求ID
        Cache.ValueWrapper cachedValue = cache.get(requestId);

        if (cachedValue != null) {
            logger.info("重复请求，操作已经执行");
            throw new RuntimeException("重复请求，操作已经执行");
        }

        cache.put(requestId, "processed");
    }
}
